﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ExpressionSerialization
{
  public static class ReflectionExtensions
  {

    public static object GetValue(this MemberInfo member, object instance)
    {
      switch(member.MemberType) {
        case MemberTypes.Property:
        return ((PropertyInfo)member).GetValue(instance, null);
        case MemberTypes.Field:
        return ((FieldInfo)member).GetValue(instance);
        default:
        throw new InvalidOperationException();
      }
    }

    public static void SetValue(this MemberInfo member, object instance, object value)
    {
      switch(member.MemberType) {
        case MemberTypes.Property:
        var pi = (PropertyInfo)member;
        pi.SetValue(instance, value, null);
        break;
        case MemberTypes.Field:
        var fi = (FieldInfo)member;
        fi.SetValue(instance, value);
        break;
        default:
        throw new InvalidOperationException();
      }
    }


    public static string ToSerializableForm(this Type type)
    {
      //string ss = type.AssemblyQualifiedName;
      //ss = ss.Substring(0, ss.IndexOf(',', ss.IndexOf(',', 0) + 1));
      //return ss;

      return type.AssemblyQualifiedName;
    }

    public static Type TypeFromSerializableForm(string serializedValue_,Type dataContract_)
    {
      Type res = null;
      res = Type.GetType(serializedValue_);
      if(res == null && serializedValue_.Contains('[')) {
        // name space
        string dcType2 = dataContract_.AssemblyQualifiedName;
        string nameType2 = dcType2.Substring(0, dcType2.IndexOf(','));
        int i1 = serializedValue_.IndexOf(nameType2);
        int i2 = serializedValue_.IndexOf(']',i1);
        string dcType1 = serializedValue_.Substring(i1,i2-i1);
        string newSerializedValue = serializedValue_.Replace(dcType1, dcType2);
        res = Type.GetType(newSerializedValue);
         
        // pozice
        // konec  definice ]
        // nahrada
      } else {
        if(res == null) {
          // Hledám podle typu a assembly bez verze a token
          var s1 = serializedValue_.Substring(0, serializedValue_.IndexOf(',', serializedValue_.IndexOf(',', 0) + 1));
          res = Type.GetType(s1);
        }
        if(res == null) {
          // Hledám podle typu bez assembly
          var s2 = serializedValue_.Substring(0, serializedValue_.IndexOf(','));
          res = Type.GetType(s2);
        }
        if(res == null) {
          if(dataContract_ != null) {
            var aqn1 = dataContract_.AssemblyQualifiedName.Split(',');
            var aqn2 = serializedValue_.Split(',');
            aqn1[0] = aqn2[0];
            var s3 = string.Join(",", aqn1);
            res = Type.GetType(s3);
          }
        }
      }
      if(res == null) {
        res = null;
      }
      return res;
    }

  }
}
